class Projection < ActiveRecord::Base
  validates_numericality_of :bug_count
   
  ##  
  # returns the projection in the format <epoc time>,<bug count>
  # the legacy generator does not use -1 for missing projections
  # and it adds the team projections together to get the project projections
  # so we need to change any -1 to 0   
  def as_generator_csv
    #Time.parse(self.date.to_s).to_i.to_s + ',' + self.bug_count
    if bug_count < 1
      date.to_time.to_i.to_s + ',0'
    else
      date.to_time.to_i.to_s + ',' + self.bug_count.to_s
    end
  end  
  
  ##
  # renders a projection array as JSON
  # this is used in graphing
  def self.as_js_array(projection_array)
    json = '['
    
    projection_array.each do |projection|
      json += '[' + projection.date.to_time.to_i.to_s + ',\'' + projection.bug_count.to_s + '\'],'
    end
    
    return json += ']'
    
  end
  
  
  
  ##
  # deletes all of a teams projections  
  def self.delete_projections_for_team_and_bug_list(team, bug_list)
    
    saved_projections = Projection.find(:all, :conditions => {:team_id => team.id, :bug_list_id => bug_list.id } )
    
    saved_projections.each do |projection|
      projection.destroy
    end
    
  end
    
  ##  
  # returns the projections for this team and bug list based on the current
  # start date and duration in the project settings. See the doc under
  # self.best_projection for more infomation
  def self.find_projections_by_team_and_bug_list(team, bug_list)
    saved_projections = Projection.find(:all, :conditions => {:team_id => team.id, :bug_list_id => bug_list.id } )
    
    projection_date_array = team.project.projection_dates
    ## these will be the projections we return.
    
    projections = Array.new 
    
    projection_date_array.each do |required_projection_date|
      best_guess = Projection.best_projection(required_projection_date, saved_projections)
      if best_guess.nil?
        empty_projection = Projection.new(:team_id => team.id, :bug_list_id => bug_list.id, :date => required_projection_date, :bug_count => -1)
        projections.push(empty_projection)      
      else
        projections.push(best_guess)   
      end
           
    end
    return projections
  
  end
  
  ##
  # find all the projections for a given bug list
  def self.find_projections_by_bug_list(bug_list)
    
    projection_date_array = bug_list.project.projection_dates
    
    project_projections = Array.new
    
    ## populate the project projections with new projections
    projection_date_array.each do |date|
      project_projections.push(Projection.new(:date => date, :bug_count => 0))
    end
    
    ## go through each team and add up their projections
    bug_list.project.teams.each do |team|
      
      
      team_projections = Projection.find_projections_by_team_and_bug_list(team,bug_list)
      
      project_projections.each_with_index do |project_projection, index|
        if team_projections[index].bug_count > 0
          ## we use -1 to show no projection, so we have to avoid adding
          ## the -1s or our totalls end up smaller than they should be.
          project_projection.bug_count += team_projections[index].bug_count
        end
      end
    end
    
    return project_projections
    
    
  end
  
  ##
  # Projections are set by teams based on weekly increments starting at 
  # the project.projection_start_date and going out project.projection_weeks.
  #
  # it's possible and even likely that a project administrator might change 
  # the project.projection_start_date  or project.projection_weeks.
  #
  # if that happens then projections that have previously been entered for a given
  # team and bug list might be set to dates that are no longer of interest to the project
  #
  # But we don't want to throw out the existing projections because some of them might be useful.
  # for example, if the projection start date is moved one day forward from a sunday to a monday
  # the projections that were entered for sunday are still better than nothing, so we should 
  # carry them forward.
  #
  # this method does just that. in the case where there is not an exact projection match
  # it finds the best one by looking at projections close to the requred date.
  # it expexts an array of Projection Objects and a date for which it will find a projection.
  def self.best_projection(requested_date, possible_projections)
    the_answer = nil
    possible_projections.each do |possible_projection|
       if ( possible_projection.date <= requested_date && possible_projection.date > (requested_date - 1.week)   )
          ## the count found is the bug count on or before 
          the_answer = possible_projection
       else
         #logger.info("trying next projection")
       end
    end
    return the_answer
  end
  
  
  
end
